/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.jr2tecnologia.mail;


import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;

/**
 *
 * @author ronildo
 */
public class Mailbox {

    private static final Logger logger = Logger.getLogger(Mailbox.class.getName());

    private static final String SMTP_HOST = "smtp.gmail.com";
    private static final String SMTP_PORT = "465";
    private static final String IMAP_HOST = "imap.gmail.com";
    private static final String IMAP_PORT = "993";
    private static final String USER_CONTATO = "contato@smsmail.com.br";
    private static final String USER_SMS = "sms@smsmail.com.br";
    private static final String PWD_CONTATO = "F3NTgGRlhgqRYs";
    private static final String PWD_SMS = "I0mRTnIcetIGptDbWiN9";

    public static boolean post(String to, String phone, String message){
        boolean sendered = false; int maxRetry = 10;
        for(int i = 0; !sendered && i <= maxRetry; maxRetry--){
            sendered = post(new String[]{to}, "SMSMail from: "+phone, message, "contato@smsmail.com.br");
            try{Thread.sleep(2000);}catch(Exception ex){}
        }
        return sendered;
    }

    public static boolean postNewUser(String to, String activationKey){
        boolean sendered = false; int maxRetry = 10;
        for(int i = 0; !sendered && i <= maxRetry; maxRetry--){
            String link = "<a href=\"http://www.smsmail.com.br/clientweb/loginListener?email="+to+"&activation_key="+activationKey+"\">aqui</a>";
            String msg = "Simples rápido e fácil, click "+link+" para confirmar seu cadastro e depois leia as instruções de uso para um melhor aproveitamento da ferramenta.";
            sendered = post(new String[]{"ronildo@jr2tecnologia.com.br","antonio@jr2tecnologia.com.br",to}, "Confirmação de cadastro", msg, "contato@smsmail.com.br");
            try{Thread.sleep(2000);}catch(Exception ex){}
        }
        return sendered;
    }

    public static boolean postBoleto(String to, String urlBoleto){
        boolean sendered = false; int maxRetry = 10;
        for(int i = 0; !sendered && i <= maxRetry; maxRetry--){
            String link = "<a href=\""+urlBoleto+"\">aqui</a>";
            String msg = "Simples rápido e fácil, click "+link+" para emitir seu boleto bancário.";
            sendered = post(new String[]{"ronildo@jr2tecnologia.com.br",to}, "Emissão de boleto bancário", msg, "contato@smsmail.com.br");
            try{Thread.sleep(2000);}catch(Exception ex){}
        }
        return sendered;
    }

    public static boolean post(String recipients[], String subject, String message, String from){
        boolean sendered = false; int maxRetry = 10;
        for(int i = 0; !sendered && i <= maxRetry; maxRetry--){
            sendered = sendMail(recipients, subject, message, from);
            try{Thread.sleep(2000);}catch(Exception ex){}
        }
        return sendered;
    }

    private static boolean sendMail(String recipients[], String subject, String message, String from){
        Properties props = System.getProperties();
        props.put("mail.transport.protocol", "smtp"); //define protocolo de envio como SMTP
        props.put("mail.smtp.starttls.enable","true");
        props.put("mail.smtp.host", SMTP_HOST); //server SMTP do GMAIL
        props.put("mail.smtp.auth", "true"); //ativa autenticacao
        props.put("mail.smtp.user", USER_CONTATO); //usuario ou seja, a conta que esta enviando o email (tem que ser do GMAIL)
        props.put("mail.debug", "false");
        props.put("mail.smtp.port", SMTP_PORT); //porta
        props.put("mail.smtp.socketFactory.port", SMTP_PORT); //mesma porta para o socket
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.socketFactory.fallback", "false");
        Session session = Session.getDefaultInstance(props, new ContactMailboxAuthenticator());
        session.setDebug(false);

        Message msg = new MimeMessage(session);
        try{
            InternetAddress[] addressTo = new InternetAddress[recipients.length];
            for (int i = 0; i < recipients.length; i++)
                addressTo[i] = new InternetAddress(recipients[i]);
            msg.setFrom(new InternetAddress(from));
            msg.setRecipients(Message.RecipientType.TO, addressTo);
            msg.setSubject(subject);
            msg.setContent(message, "text/html");
            msg.saveChanges();
        
            Transport tr = session.getTransport("smtp"); //define smtp para transporte  
            tr.connect(SMTP_HOST, USER_CONTATO, PWD_CONTATO);
            tr.sendMessage(msg, msg.getAllRecipients());  
            tr.close();

            return true;
        } catch (MessagingException ex) {
            logger.log(Level.SEVERE, "cannot send sms", ex);
            return false;
        }
    }

    public static List<SMSMail> read(){
        logger.info("Iniciando leitura da caixa de mail "+USER_SMS);
        List<SMSMail> listMailbox = new LinkedList<SMSMail>();
        Properties props = System.getProperties();
        props.setProperty("mail.imaps.host", IMAP_HOST);
        props.setProperty("mail.imap.port", IMAP_PORT);
        props.setProperty("mail.store.protocol", "imaps");
        props.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.setProperty("mail.imap.socketFactory.fallback", "false");
        Session session = Session.getDefaultInstance(props, new SMSMailboxAuthenticator());

        try{
            // Get the store
            Store store = session.getStore();
            store.connect();

            // Get folder INBOX
            Folder folderInbox = store.getFolder("INBOX");
            folderInbox.open(Folder.READ_WRITE);
            listMailbox.addAll(readFolder(folderInbox));
            folderInbox.close(true);

            store.close();

        }catch(Exception e){
            logger.log(Level.SEVERE, "cannot read mail box",e);
        }
        return listMailbox;
    }

    private static List<SMSMail> readFolder(Folder folder) throws Exception {
        List<SMSMail> listMailbox = new LinkedList<SMSMail>();
        // Get directory
        Message messages[] = folder.getMessages();
        for (int x = 0; x < messages.length; x++) {
            Message message = messages[x];
            Address to[] = message.getRecipients(Message.RecipientType.TO);
            for (int y = 0; to != null && y < to.length; y++) {
                SMSMail smsMail = new SMSMail();
                smsMail.setFrom(message.getFrom());
                smsMail.setTo(to[y].toString());
                smsMail.setPhone(to[y].toString());
                smsMail.setSubject(message.getSubject());

                if (smsMail.getPhone() != null) {

                    Object object = message.getContent();
                    if(object instanceof String){
                        smsMail.setMessage(object.toString());
                        listMailbox.add(smsMail);
                    }else{
                        Multipart multipart = (Multipart) object;
                        for (int i = 0, n = multipart.getCount(); i < n; i++) {
                            BodyPart bodyPart = multipart.getBodyPart(i);
                            MimeBodyPart mbp = (MimeBodyPart) bodyPart;
                            if (mbp.isMimeType("text/plain")) {
                                smsMail.setMessage(mbp.getContent());
                                listMailbox.add(smsMail);
                                logger.info("email from <" + smsMail.getFrom() + "> to <" + smsMail.getTo() + "> successfully processed");
                            }
                        }
                    }
                } else {
                    post(new String[]{smsMail.getFrom()}, "Numero de telefone inválido", "Desculpas mas não conseguimos processar esse numero de telefone " + smsMail.getTo(), "contato@smsmail.com.br");
                }
            }
            message.setFlag(Flags.Flag.DELETED, true);
        }
        return listMailbox;
    }

    private static final class ContactMailboxAuthenticator extends Authenticator {
        @Override
        public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(USER_CONTATO, PWD_CONTATO);
        }
    }

    private static final class SMSMailboxAuthenticator extends Authenticator {
        @Override
        public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(USER_SMS, PWD_SMS);
        }
    }
    
}
